/* -*- c++ -*- */
/*
 *   Copyright 2011,2012 Erik Persson
 *
 *   This file is part of the cell-sync-usrp project.
 *
 *   cell-sync-usrp is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   cell-sync-usrp is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with cell-sync-usrp.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * config.h is generated by configure.  It contains the results
 * of probing for features, options etc.  It should be the first
 * file included in your .cc file.
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <wcdma_resampler_cc.h>
#include <gr_io_signature.h>
#include <iostream>

/*
 * Create a new instance of wcdma_resampler_cc and return
 * a boost shared_ptr.  This is effectively the public constructor.
 */
wcdma_resampler_cc_sptr
wcdma_make_resampler_cc (float scale)
{
  return wcdma_resampler_cc_sptr (new wcdma_resampler_cc (scale));
}

/*
 * Specify constraints on number of input and output streams.
 * This info is used to construct the input and output signatures
 * (2nd & 3rd args to gr_block's constructor).  The input and
 * output signatures are used by the runtime system to
 * check that a valid number and type of inputs and outputs
 * are connected to this block.  In this case, we accept
 * only 1 input and 1 output.
 */
static const int MIN_IN = 1;	// mininum number of input streams
static const int MAX_IN = 1;	// maximum number of input streams
static const int MIN_OUT = 1;	// minimum number of output streams
static const int MAX_OUT = 1;	// maximum number of output streams

/*
 * The private constructor
 */
wcdma_resampler_cc::wcdma_resampler_cc (float scale)
  : gr_block ("resampler_cc",
	      gr_make_io_signature (MIN_IN, MAX_IN, sizeof (gr_complex)),
	      gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (gr_complex)))
{
  this->d_scale = scale;				// setting the scaling factor
  //this->d_scale = 7.692308/7.68;
  this->d_position = 0;					// setting the initial stepping position
  this->d_scale_position = 0.0f;		// setting the initial scale stepping position
  this->d_last = gr_complex(0.0f,0.0f);	// setting the initial last received buffered sample
  this->d_in_startup_state = true;		// indicate that we're in startup state
}

/*
 * Our virtual destructor.
 */
wcdma_resampler_cc::~wcdma_resampler_cc ()
{
  // nothing else required in this example
}

int
wcdma_resampler_cc::general_work (int noutput_items,
			       gr_vector_int &ninput_items,
			       gr_vector_const_void_star &input_items,
			       gr_vector_void_star &output_items)
{
  const gr_complex *in = (const gr_complex *) input_items[0];
  gr_complex *out = (gr_complex *) output_items[0];

  int created_output = 0;

  // loop through all the recieved inputs
  for (int i = 0; i < noutput_items; i++){

	  if (this->d_in_startup_state == true){// if in startup state
		  this->d_last = in[i];				// put input in last received sample buffer
		  this->d_in_startup_state = false;	// switch state for next received input

	  } else {								// if not in startup state

		  this->d_position++;				// increase position
		  if (this->d_position > this->d_scale_position){
			  while (this->d_position > this->d_scale_position){
				  // we got samples to create

				  // sample
				  gr_complex sample = this->sample(this->d_last,in[i],this->d_position-this->d_scale_position);

				  // send the new sample to output
				  out[created_output] = sample;
				  created_output++;

				  // calculate next sampling position
				  this->d_scale_position += this->d_scale;
			  }

			  this->d_scale_position -= this->d_position;
			  this->d_position = 0;
		  }

		  this->d_last = in[i];

	  }
  }

  // Tell runtime system how many input items we consumed on
  // each input stream.

  consume_each (noutput_items);

  // Tell runtime system how many output items we produced.
  return created_output;
}

gr_complex wcdma_resampler_cc::sample(gr_complex s1, gr_complex s2, float a){
	return s1*(1-a) + s2*(a);
}
